package stc.skymobi.netty.handler.codec.esb;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import stc.skymobi.bean.bytebean.core.BeanFieldCodec;
import stc.skymobi.bean.esb.core.EsbHeaderable;
import stc.skymobi.netty.handler.codec.access.AccessSignalCodecUtils;
import stc.skymobi.netty.handler.codec.access.protocol.signal.AbstractEsbT2ASignal;
import stc.skymobi.transport.protocol.esb.codec.EsbSignalCodecUtils;
import stc.skymobi.util.ByteUtils;


public class NettyEsbEncoder extends MessageToByteEncoder {

    private static final Logger logger = LoggerFactory.getLogger(NettyEsbEncoder.class);

    private BeanFieldCodec esbBeanCodec;
    private int dumpBytes = 256;
    private boolean isDebugEnabled;
    private int myESBAddr;

    @Override
    public void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out)
            throws Exception {

        byte[] bytes;
        if (msg instanceof AbstractEsbT2ASignal) {
            bytes = AccessSignalCodecUtils.encodeSignal(
                    (EsbHeaderable) msg, esbBeanCodec, myESBAddr);
        } else {
            bytes = EsbSignalCodecUtils.encodeSignal(
                    (EsbHeaderable) msg, esbBeanCodec, myESBAddr);
        }

        if (null != bytes) {
            if (logger.isDebugEnabled() && isDebugEnabled) {
                logger.debug("channel {} \r\nsend signal {}", ctx.channel(), msg);
            }
            if (logger.isTraceEnabled() && isDebugEnabled) {
                logger.trace("and raw bytes \r\n{}",
                        ByteUtils.bytesAsHexString(bytes, dumpBytes));
            }
        } else {
            logger.error("encode: " + msg + " can not generate byte stream.");
        }
        out.writeBytes(bytes);
    }

    /**
     * @return the myESBAddr
     */
    public int getMyESBAddr() {
        return myESBAddr;
    }

    /**
     * @param myESBAddr the myESBAddr to set
     */
    public void setMyESBAddr(int myESBAddr) {
        this.myESBAddr = myESBAddr;
    }

    /**
     * @return the esbBeanCodec
     */
    public BeanFieldCodec getEsbBeanCodec() {
        return esbBeanCodec;
    }

    /**
     * @param esbBeanCodec the esbBeanCodec to set
     */
    public void setEsbBeanCodec(BeanFieldCodec esbBeanCodec) {
        this.esbBeanCodec = esbBeanCodec;
    }

    public boolean isDebugEnabled() {
        return isDebugEnabled;
    }

    public void setDebugEnabled(boolean isDebugEnabled) {
        this.isDebugEnabled = isDebugEnabled;
    }

    public int getDumpBytes() {
        return dumpBytes;
    }

    /**
     * @param dumpBytes the dumpBytes to set
     */
    public void setDumpBytes(int dumpBytes) {
        this.dumpBytes = dumpBytes;
    }
}
